﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using NDK.Frm;
using NDK.Module.Model;
using Newtonsoft.Json;

namespace NDK.Module.StationLogic
{

    public class SunWayOEEYieldDay
    {
        [Description("")]
        public string Name { get; set; }

        [Description("08:00-10:00")]
        public string Time4 { get; set; } = "0";

        [Description("10:00-12:00")]
        public string Time5 { get; set; } = "0";

        [Description("12:00-14:00")]
        public string Time6 { get; set; } = "0";

        [Description("14:00-16:00")]
        public string Time7 { get; set; } = "0";

        [Description("16:00-18:00")]
        public string Time8 { get; set; } = "0";

        [Description("18:00-20:00")]
        public string Time9 { get; set; } = "0";

        [Description("总计")]
        public string Total { get; set; } = "0";

    }

    public class SunWayOEEYieldNight
    {
        [Description("")]
        public string Name { get; set; }

        [Description("20:00-22:00")]
        public string Time10 { get; set; } = "0";

        [Description("22:00-24:00")]
        public string Time11 { get; set; } = "0";

        [Description("00:00-02:00")]
        public string Time0 { get; set; } = "0";

        [Description("02:00-04:00")]
        public string Time1 { get; set; } = "0";

        [Description("04:00-06:00")]
        public string Time2 { get; set; } = "0";

        [Description("06:00-08:00")]
        public string Time3 { get; set; } = "0";

        [Description("总计")]
        public string Total { get; set; }
    }

    public class SunWayOEEYieldUpLoad
    {
        public string StartTime { get; set; }
        public string EndTime { get; set; }
        public string TotalProduction { get; set; }
        public string OKTotal { get; set; }
        public string NGTotal { get; set; }
        public string ProductYield { get; set; }
        public string Activation { get; set; }
        public string UPH { get; set; }
        public List<Defect> Defect { get; set; } = new List<Defect>();
    }

    public class Defect
    {
        public string Defect_Type { get; set; }
        public int Defect_Qty { get; set; }
    }

    public class DefectType
    {
        public string Defect_Type { get; set; }
        public List<string> FAIName { get; set; }
    }

    public class SunWayOEEYieldUpLoadMethod
    {
        protected readonly string OEEYieldDefectFilePath = $"{Environment.CurrentDirectory}\\Config\\SunWayOEEDefect.json";
        protected readonly List<DefectType> defects = new List<DefectType>();
        public SunWayOEEYieldUpLoadMethod()
        {
            if (File.Exists(OEEYieldDefectFilePath))
            {
                defects = JsonConvert.DeserializeObject<List<DefectType>>(File.ReadAllText(OEEYieldDefectFilePath));
            }
            else
            {
                defects = new List<DefectType>();
                for (int i = 0; i < 6; i++)
                {
                    defects.Add(new DefectType() { Defect_Type = $"DefectType{i}", FAIName = new List<string>() });
                    for (int j = 0; j < 20; j++)
                    {
                        defects[i].FAIName.Add($"FAI{j}");
                    }
                }
                string str = JsonConvert.SerializeObject(defects, Formatting.Indented);
                File.WriteAllText(OEEYieldDefectFilePath, str);
            }
        }

        public void Upload()
        {
            DateTime time = DateTime.Now;
            List<SunWayOEEYieldUpLoad> upLoads = new List<SunWayOEEYieldUpLoad>();
            var shift = (int)(Math.Ceiling((double)(time.Hour / 2)));
            if (shift <= 3 || shift >= 10)
            {
                int[] ints = new int[6] { 10, 11, 0, 1, 2, 3 };
                List<string> def = new List<string>();
                foreach (var item in Common.OEEYieldMethod.Nights)
                {
                    if (item.Name.Contains("FAI"))
                    {
                        def.Add(item.Name);
                    }
                }
                for (int i = 0; i < 6; i++)
                {
                    upLoads.Add(new SunWayOEEYieldUpLoad());
                    var pro = typeof(SunWayOEEYieldNight).GetProperty($"Time{ints[i]}");
                    upLoads[i].StartTime = $"{(ints[i] * 2).ToString().PadLeft(2, '0')}:00";
                    upLoads[i].EndTime = $"{(ints[i] * 2 + 2).ToString().PadLeft(2, '0')}:00";
                    upLoads[i].UPH = pro.GetValue(Common.OEEYieldMethod.Nights[0]).ToString();
                    upLoads[i].TotalProduction = pro.GetValue(Common.OEEYieldMethod.Nights[1]).ToString();
                    upLoads[i].OKTotal = pro.GetValue(Common.OEEYieldMethod.Nights[2]).ToString();
                    upLoads[i].NGTotal = pro.GetValue(Common.OEEYieldMethod.Nights[3]).ToString();
                    upLoads[i].ProductYield = pro.GetValue(Common.OEEYieldMethod.Nights[4]).ToString();
                    upLoads[i].Activation = Common.OEETimeMethod.OEEs[ints[i]].PAR;
                }
                foreach (var item in defects)
                {
                    foreach (var item1 in item.FAIName)
                    {
                        if (def.Contains(item1))
                        {
                            for (int i = 0; i < 6; i++)
                            {
                                var pro = typeof(SunWayOEEYieldNight).GetProperty($"Time{ints[i]}");
                                if (upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type) == null)
                                {
                                    upLoads[i].Defect.Add(new Defect() { Defect_Type = item.Defect_Type, Defect_Qty = int.Parse(pro.GetValue(Common.OEEYieldMethod.Nights.SingleOrDefault(x => x.Name == item1)).ToString()) });
                                }
                                else
                                {
                                    int count = upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type).Defect_Qty;
                                    upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type).Defect_Qty = count += int.Parse(pro.GetValue(Common.OEEYieldMethod.Nights.SingleOrDefault(x => x.Name == item1)).ToString());
                                }
                            }
                        }
                    }
                }
            }
            else if (shift >= 4 && shift <= 9)
            {
                int[] ints = new int[6] { 4, 5, 6, 7, 8, 9 };
                List<string> def = new List<string>();
                foreach (var item in Common.OEEYieldMethod.Days)
                {
                    if (item.Name.Contains("FAI"))
                    {
                        def.Add(item.Name);
                    }
                }
                for (int i = 0; i < 6; i++)
                {
                    upLoads.Add(new SunWayOEEYieldUpLoad());
                    var pro = typeof(SunWayOEEYieldDay).GetProperty($"Time{ints[i]}");
                    upLoads[i].StartTime = $"{(ints[i] * 2).ToString().PadLeft(2, '0')}:00";
                    upLoads[i].EndTime = $"{(ints[i] * 2 + 2).ToString().PadLeft(2, '0')}:00";
                    upLoads[i].UPH = pro.GetValue(Common.OEEYieldMethod.Days[0]).ToString();
                    upLoads[i].TotalProduction = pro.GetValue(Common.OEEYieldMethod.Days[1]).ToString();
                    upLoads[i].OKTotal = pro.GetValue(Common.OEEYieldMethod.Days[2]).ToString();
                    upLoads[i].NGTotal = pro.GetValue(Common.OEEYieldMethod.Days[3]).ToString();
                    upLoads[i].ProductYield = pro.GetValue(Common.OEEYieldMethod.Days[4]).ToString();
                    upLoads[i].Activation = Common.OEETimeMethod.OEEs[ints[i]].PAR;
                }
                foreach (var item in defects)
                {
                    foreach (var item1 in item.FAIName)
                    {
                        if (def.Contains(item1))
                        {
                            for (int i = 0; i < 6; i++)
                            {
                                var pro = typeof(SunWayOEEYieldDay).GetProperty($"Time{ints[i]}");
                                if (upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type) == null)
                                {
                                    upLoads[i].Defect.Add(new Defect() { Defect_Type = item.Defect_Type, Defect_Qty = int.Parse(pro.GetValue(Common.OEEYieldMethod.Days.SingleOrDefault(x => x.Name == item1)).ToString()) });
                                }
                                else
                                {
                                    int count = upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type).Defect_Qty;
                                    upLoads[i].Defect.SingleOrDefault(x => x.Defect_Type == item.Defect_Type).Defect_Qty = count += int.Parse(pro.GetValue(Common.OEEYieldMethod.Days.SingleOrDefault(x => x.Name == item1)).ToString());
                                }
                            }
                        }
                    }
                }
            }

            string str = JsonConvert.SerializeObject(upLoads); //序列化
            if (Common.BP_UPMES)
            {
                Common.SwMes.YieldDataUpload(str);
            }
        }
    }

    public class SunWayOEEYieldMethodd
    {
        public readonly string OEEYieldDayFilePath = $"{Environment.CurrentDirectory}\\Config\\SunWayOEEYieldDay.json";
        public readonly string OEEYieldNightFilePath = $"{Environment.CurrentDirectory}\\Config\\SunWayOEEYieldNight.json";
        public List<string> Names { get; set; } = new List<string>() { "UPH", "ToTtal", "OK", "NG", "Yield" };
        public BindingList<SunWayOEEYieldDay> Days { get; set; }
        public BindingList<SunWayOEEYieldNight> Nights { get; set; }

        public SunWayOEEYieldMethodd()
        {
            Init();
        }

        public void Init()
        {
            if (File.Exists(OEEYieldDayFilePath))
            {
                Days = JsonConvert.DeserializeObject<BindingList<SunWayOEEYieldDay>>(File.ReadAllText(OEEYieldDayFilePath));
            }
            if (File.Exists(OEEYieldNightFilePath))
            {
                Nights = JsonConvert.DeserializeObject<BindingList<SunWayOEEYieldNight>>(File.ReadAllText(OEEYieldNightFilePath));
            }
            if (Days == null)
            {
                Days = new BindingList<SunWayOEEYieldDay>();
                for (int i = 0; i < Names.Count; i++)
                {
                    Days.Add(new SunWayOEEYieldDay() { Name = Names[i] });
                }

            }
            Frm_Home.Instance.DGV_OEEYieldDay.DataSource = Days;
            foreach (DataGridViewColumn item in Frm_Home.Instance.DGV_OEEYieldDay.Columns)
            {
                var property = typeof(SunWayOEEYieldDay).GetProperty(item.HeaderText);
                if (property != null)
                {
                    var attributes = property.GetCustomAttribute<DescriptionAttribute>().Description;
                    item.HeaderText = attributes;
                }
            }
            if (Nights == null)
            {
                Nights = new BindingList<SunWayOEEYieldNight>();
                for (int i = 0; i < Names.Count; i++)
                {
                    Nights.Add(new SunWayOEEYieldNight() { Name = Names[i] });
                }
            }
            Frm_Home.Instance.DGV_OEEYieldNight.DataSource = Nights;
            foreach (DataGridViewColumn item in Frm_Home.Instance.DGV_OEEYieldNight.Columns)
            {
                var property = typeof(SunWayOEEYieldNight).GetProperty(item.HeaderText);
                if (property != null)
                {
                    var attributes = property.GetCustomAttribute<DescriptionAttribute>().Description;
                    item.HeaderText = attributes;
                }
            }
        }

        /// <summary>
        /// 更新数据至Json文件
        /// </summary>
        /// <returns></returns>
        public void Refresh(DateTime time, int total, int ok, List<string> NGFAI = null)
        {
            var shift = (int)(Math.Ceiling((double)(time.Hour / 2)));
            if (shift <= 3 || shift >= 10)
            {
                List<int> values = new List<int>();
                for (int i = 1; i < 3; i++)
                {
                    var prop = Nights[i].GetType().GetProperty($"Time{shift}");
                    int.TryParse(prop.GetValue(Nights[i]).ToString(), out int value);
                    values.Add(value);
                }
                int Total = values[0] + total;
                int OK = values[1] + ok;

                var prop0 = Nights[0].GetType().GetProperty($"Time{shift}");
                prop0.SetValue(Nights[0], (Total / 2).ToString());

                var prop1 = Nights[1].GetType().GetProperty($"Time{shift}");
                prop1.SetValue(Nights[1], Total.ToString());

                var prop2 = Nights[2].GetType().GetProperty($"Time{shift}");
                prop2.SetValue(Nights[2], OK.ToString());

                var prop3 = Nights[3].GetType().GetProperty($"Time{shift}");
                prop3.SetValue(Nights[3], (Total - OK).ToString());

                var prop4 = Nights[4].GetType().GetProperty($"Time{shift}");
                prop4.SetValue(Nights[4], Math.Round((double)OK / Total, 2).ToString());
                if (NGFAI != null)
                {
                    foreach (var item in NGFAI)
                    {
                        if (Nights.SingleOrDefault(x => x.Name == item) == null)
                        {
                            Nights.Add(new SunWayOEEYieldNight() { Name = item });
                        }
                        var item1 = Nights.SingleOrDefault(x => x.Name == item);
                        var propp = item1.GetType().GetProperty($"Time{shift}");
                        int.TryParse(propp.GetValue(item1).ToString(), out int count);
                        propp.SetValue(item1, (count += 1).ToString());
                    }
                }
                for (int i = 0; i < Nights.Count; i++)
                {
                    Nights[i].Total = (double.Parse(Nights[i].Time0) + double.Parse(Nights[i].Time1) + double.Parse(Nights[i].Time2) + double.Parse(Nights[i].Time3) + double.Parse(Nights[i].Time10) + double.Parse(Nights[i].Time11)).ToString();
                    if (i == 0)
                    {
                        Nights[i].Total = Math.Round(double.Parse(Nights[i].Total) / 12, 2).ToString();
                    }
                    if (i == 4)
                    {
                        Nights[i].Total = Math.Round(double.Parse(Nights[2].Total) / double.Parse(Nights[1].Total), 2).ToString();
                    }
                }
                Frm_Home.Instance.DGV_OEEYieldNight.Refresh();
                string str = JsonConvert.SerializeObject(Nights, Formatting.Indented);
                File.WriteAllText(OEEYieldNightFilePath, str);
            }
            else if (shift >= 4 && shift <= 9)
            {
                List<int> values = new List<int>();
                for (int i = 1; i < 3; i++)
                {
                    var prop = Days[i].GetType().GetProperty($"Time{shift}");
                    int.TryParse(prop.GetValue(Days[i]).ToString(), out int value);
                    values.Add(value);
                }
                int Total = values[0] + total;
                int OK = values[1] + ok;

                var prop0 = Days[0].GetType().GetProperty($"Time{shift}");
                prop0.SetValue(Days[0], (Total / 2).ToString());

                var prop1 = Days[1].GetType().GetProperty($"Time{shift}");
                prop1.SetValue(Days[1], Total.ToString());

                var prop2 = Days[2].GetType().GetProperty($"Time{shift}");
                prop2.SetValue(Days[2], OK.ToString());

                var prop3 = Days[3].GetType().GetProperty($"Time{shift}");
                prop3.SetValue(Days[3], (Total - OK).ToString());

                var prop4 = Days[4].GetType().GetProperty($"Time{shift}");
                prop4.SetValue(Days[4], Math.Round((double)OK / Total, 2).ToString());

                if (NGFAI != null)
                {
                    foreach (var item in NGFAI)
                    {
                        if (Days.SingleOrDefault(x => x.Name == item) == null)
                        {
                            Days.Add(new SunWayOEEYieldDay() { Name = item });
                        }
                        var item1 = Days.SingleOrDefault(x => x.Name == item);
                        var propp = item1.GetType().GetProperty($"Time{shift}");
                        int.TryParse(propp.GetValue(item1).ToString(), out int count);
                        propp.SetValue(item1, (count += 1).ToString());
                    }
                }
                for (int i = 0; i < Days.Count; i++)
                {
                    Days[i].Total = (double.Parse(Days[i].Time4) + double.Parse(Days[i].Time5) + double.Parse(Days[i].Time6) + double.Parse(Days[i].Time7) + double.Parse(Days[i].Time8) + double.Parse(Days[i].Time9)).ToString();
                    if (i == 0)
                    {
                        Days[i].Total = Math.Round(double.Parse(Days[i].Total) / 12, 2).ToString();
                    }
                    if (i == 4)
                    {
                        Days[i].Total = Math.Round(double.Parse(Days[2].Total) / double.Parse(Days[1].Total), 2).ToString();
                    }
                }
                Frm_Home.Instance.DGV_OEEYieldDay.Refresh();
                string str = JsonConvert.SerializeObject(Days, Formatting.Indented);
                File.WriteAllText(OEEYieldDayFilePath, str);
            }
        }
    }
}
